<?php
/**
 * RcPHP class file.
 *
 * @author         RcPHP Dev Team
 * @copyright      Copyright (c) 2013,RcPHP Dev Team
 * @license        Apache License 2.0 {@link http://www.apache.org/licenses/LICENSE-2.0}
 * @package        Core
 * @since          1.0
 */
namespace RCPHP;

use RCPHP\Util\Check;

defined('IN_RCPHP') or exit('Access denied');

class RcPHP
{

	/**
	 * Controller Name
	 *
	 * @var string
	 */
	public static $_controller;

	/**
	 * Action name
	 *
	 * @var string
	 */
	public static $_action;

	/**
	 * Function method
	 *
	 * @var array
	 */
	public static $_params = array();

	/**
	 * Include file hash
	 *
	 * @var array
	 */
	public static $_includes = array();

	/**
	 * Config hash
	 *
	 * @var array
	 */
	private static $_config = array();

	/**
	 * Object hash
	 *
	 * @var array
	 */
	private static $_instance = array();

	/**
	 * Create App Process
	 *
	 * @return object
	 */
	public static function run()
	{
		self::registerAutoload();
		self::registerHandler();

		if(APP_DEBUG === true)
		{
			Debug::start();
		}

		self::loadFile(RCPHP_PATH . 'Core' . DS . 'Structure.class.php');
		self::loadFile(RCPHP_PATH . 'Core' . DS . 'Route.class.php');
		self::loadFile(RCPHP_PATH . 'Core' . DS . 'Log.class.php');

		Structure::run();
		Route::dispatch();
		Log::config();

		$controllerFile = CONTROLLER_PATH . self::$_controller . 'Controller.class.php';

		if(file_exists($controllerFile))
		{
			self::loadFile($controllerFile);
		}
		else
		{
			Controller::halt("The controller file does not exist");
		}

		$controller = self::$_controller . "Controller";
		$controller = defined('APP_NAMESPACE') ? rtrim(APP_NAMESPACE, "\\") . "\\" . $controller : $controller;

		$appObject = self::instance($controller);

		if(method_exists($controller, self::$_action))
		{
			call_user_func_array(array(
				&$appObject,
				self::$_action
			), self::$_params);
		}
		else
		{
			Controller::halt('The controller method ' . self::$_action . ' does not exist');
		}

		if(APP_DEBUG === true)
		{
			Debug::output();
		}
	}

	/**
	 * Registered automatically load.
	 *
	 * @return void
	 */
	public static function registerAutoload()
	{
		self::loadFile(RCPHP_PATH . 'Core' . DS . 'Loader.class.php');

		Loader::registerAutoloader();
	}

	/**
	 * Register handler.
	 *
	 * @return void
	 */
	public static function registerHandler()
	{
		register_shutdown_function(array(
			"RCPHP\\Debug",
			"fatalError"
		));
		set_error_handler(array(
			"RCPHP\\Debug",
			"appError"
		));
		set_exception_handler(array(
			"RCPHP\\Debug",
			"appException"
		));
	}

	/**
	 * Controller Name
	 *
	 * @return string
	 */
	public static function getController()
	{
		return self::$_controller;
	}

	/**
	 * Action Name
	 *
	 * @return string
	 */
	public static function getAction()
	{
		return self::$_action;
	}

	/**
	 * Params
	 *
	 * @return array
	 */
	public static function getParams()
	{
		return self::$_params;
	}

	/**
	 * Request method.
	 *
	 * @return string
	 */
	public static function getMethod()
	{
		return Check::isAjax() ? "Ajax" : $_SERVER['REQUEST_METHOD'];
	}

	/**
	 * Configuration information
	 *
	 * @param string $fileName
	 * @return array
	 */
	public static function getConfig($fileName)
	{
		if(empty(self::$_config[$fileName]))
		{
			$filePath = CONF_PATH . $fileName . '.php';

			if(file_exists($filePath))
			{
				self::$_config[$fileName] = include_once $filePath;
			}
		}

		return !empty(self::$_config[$fileName]) ? self::$_config[$fileName] : false;
	}

	/**
	 * String the version of RcPHP framework.
	 *
	 * @return string
	 */
	public static function getVersion()
	{
		return RCPHP_VERSION;
	}

	/**
	 * The singleton pattern returns the instance
	 *
	 * @param string $class
	 * @param string $method
	 * @return object
	 */
	public static function instance($class, $method = '', $params = array())
	{
		$key = $class . $method;

		if(!isset(self::$_instance[$key]))
		{
			if(class_exists($class))
			{
				$obj = new $class;

				if(!empty($method) && method_exists($class, $method))
				{
					self::$_instance[$key] = call_user_func(array(
						&$obj,
						$method
					), $params);
				}
				else
				{
					self::$_instance[$key] = $obj;
				}
			}
			else
			{
				Controller::halt("The " . $class . " class file does not exist");
			}
		}

		return self::$_instance[$key];
	}

	/**
	 * Static load file is not repeated loading
	 *
	 * @param string $fileName
	 * @return bool
	 */
	public static function loadFile($fileName)
	{
		if(empty($fileName))
		{
			return false;
		}

		//Judgment document ever loaded, loaded directly returns true
		if(!isset(self::$_includes[$fileName]) && file_exists($fileName))
		{

			//load file.
			include_once $fileName;
			self::$_includes[$fileName] = true;
		}

		return !empty(self::$_includes[$fileName]) ? self::$_includes[$fileName] : false;
	}
}
